/**
 * Created by Administrator on 2017/1/18.
 */

var MJ = require("./MJ.js");

function HangupTask(room) {
    this.room = room;
    this.players = {        // 有挂起任务的玩家及任务信息
        /*
        $playerIndex: {
            $task: {}
        }*/
    };

    this.submits = {};      // 已经提交任务的玩家

    this.source = {};       // 导致挂起任务的来源

    this.passHandler = null;        // 所有任务都pass后的回调函数
    this.passHandlerArgs = null;
}

HangupTask.prototype = {
    reset: function() {
        this.players = {};
        this.submits = {};

        this.source = {};
        this.passHandler = null;
        this.passHandlerArgs = null;
    },

    /**
     * 添加任务
     * @param playerIndex 玩家坐位号
     * @param task 任务编号，见MJ.Task中的定义
     * @param taskInfo 任务信息
     */
    addTask: function(playerIndex, task, taskInfo) {
        var playerTask = this.players[playerIndex];
        if (!playerTask) {
            playerTask = {};
            this.players[playerIndex] = playerTask;
        }

        playerTask[task] = taskInfo || {};
    },

    addHuTask: function(playerIndex, card, from, pattern, rules) {
        if (ExObject.isObject(card)) {
            var task = card;
            this.addTask(playerIndex, MJ.Task.HU, task);
            return;
        }

        this.addTask(playerIndex, MJ.Task.HU, {card: card, from: from, pattern: pattern, rules: rules || []});
    },

    addGangTask: function(playerIndex, card, from, gang, overdue) {
        if (ExObject.isArray(card)) {
            var gangArray = card;
            this.addTask(playerIndex, MJ.Task.GANG, {gangArray: gangArray});
            return;
        }

        if (ExObject.isObject(card)) {
            var gangTask = card;
            this.addTask(playerIndex, MJ.Task.GANG, gangTask);
            return;
        }

        var gangTask = {card: card, from: from, gang: gang};
        if (overdue) {
            gangTask.overdue = overdue;
        }
        this.addTask(playerIndex, MJ.Task.GANG, gangTask);
    },

    addPengTask: function(playerIndex, card, from) {
        this.addTask(playerIndex, MJ.Task.PENG, {card: card, from: from});
    },

    addChiTask: function(playerIndex, card, from, maxCards) {
        this.addTask(playerIndex, MJ.Task.CHI, {card: card, from: from, maxCards: maxCards});
    },

    addTingTask: function(playerIndex, tings) {
        this.addTask(playerIndex, MJ.Task.TING, {tings: tings});
    },

    /**
     * 是否存在任务
     * @param playerIndex 坐位号，可选，有此参数则判断某坐位号的玩家是否有任务，否则判断所有玩家是否有任务
     * @returns {boolean}
     */
    exist: function(playerIndex) {
        if (playerIndex) {
            return this.players.hasOwnProperty(playerIndex);
        } else {
            return Object.keys(this.players).length > 0;
        }
    },

    /**
     * 除某坐位玩家后是否有其它玩家的任务
     * @param playerIndex
     * @returns {boolean}
     */
    existOther: function(playerIndex) {
        var result = false;
        ExObject.eachKeyNum(this.players, function(eIndex, eTask) {
            if (eIndex != playerIndex) {
                result = true;
            }
        });
        return result;
    },

    /**
     * 某坐位玩家是否存在某种任务
     * @param playerIndex 玩家坐位号
     * @param task 任务编号
     * @returns {boolean}
     */
    existTask: function(playerIndex, task) {
        var playerTask = this.players[playerIndex];
        if (!playerTask) {
            return false;
        }
        return (playerTask.hasOwnProperty(task));
    },

    existUncommitted: function(playerIndex) {
        var exist = false;

        if (playerIndex) {
            var playerTasks = this.players[playerIndex];
            if (playerTasks && !this.submits.hasOwnProperty(playerIndex)) {
                exist = true;
            }
        } else {
            this.enumUncommitted(function(eIndex, eTask) {
                exist = true;
            });
        }

        return exist;
    },

    _submitPassUncommittedIfNotExistTasks: function(tasks) {
        this.enumUncommitted(function(eIndex, eTasks) {
            var notExist = true;
            tasks.forEach(function(task) {
                if (eTasks.hasOwnProperty(task)) {
                    notExist = false;
                }
            });

            if (notExist) {
                this.submits[eIndex] = MJ.Task.PASS;
            }
        }.bind(this));
    },

    submitTask: function(playerIndex, task, arg1) {
        this.submitTaskWithoutCheck(playerIndex, task, arg1);
        this.check();
    },

    submitTaskWithoutCheck: function(playerIndex, task, arg1) {
        var taskInfo = this.getPlayerTask(playerIndex, task);
        if (!taskInfo) {
            return;
        }

        this.submits[playerIndex] = task;

        switch (task) {
            case MJ.Task.HU:
                this._submitPassUncommittedIfNotExistTasks([MJ.Task.TING, MJ.Task.HU]);
                break;
            case MJ.Task.GANG:
                this._submitPassUncommittedIfNotExistTasks([MJ.Task.TING, MJ.Task.HU, MJ.Task.GANG]);
                if (arg1) {
                    taskInfo.selectGang = arg1;
                }
                break;
            case MJ.Task.PENG:
                this._submitPassUncommittedIfNotExistTasks([MJ.Task.TING, MJ.Task.HU, MJ.Task.GANG, MJ.Task.PENG]);
                break;
            case MJ.Task.CHI:
                if (arg1) {
                    taskInfo.selectCard = arg1;
                }
                break;
            default:
                break;
        }
    },

    submitPass: function(playerIndex) {
        this.submits[playerIndex] = MJ.Task.PASS;
        this.check();
    },

    enumUncommitted: function(handler) {
        for (var eIndex in this.players) {
            if (!this.submits.hasOwnProperty(eIndex)) {
                handler(eIndex, this.players[eIndex]);
            }
        }
    },

    getUncommitted: function(playerIndex) {
        var task = this.players[playerIndex];
        if (!task || this.submits.hasOwnProperty(playerIndex)) {
            return null;
        }
        return this.players[playerIndex];
    },

    isEmpty: function() {
        return (Object.keys(this.players).length == 0);
    },

    isCommitted: function(playerIndex) {
        return this.submits.hasOwnProperty(playerIndex);
    },

    getPlayerTask: function(playerIndex, task) {
        var tasks = this.players[playerIndex];
        if (tasks) {
            return tasks[task];
        }
    },

    getSubmitTasks: function(task) {
        var tasks = [];
        for (var playerIndex in this.submits) {
            if (this.submits[playerIndex] == task) {
                var taskInfo = this.players[playerIndex][task];
                if (taskInfo) {
                    taskInfo.playerIndex = +playerIndex;
                    tasks.push(taskInfo);
                }
            }
        }
        return tasks;
    },

    check: function() {
        var indexArr = Object.keys(this.players);
        if (indexArr.length != Object.keys(this.submits).length) {
            return;
        }


        var tingTasks = this.getSubmitTasks(MJ.Task.TING);
        if (tingTasks.length > 0) {
            this.room.onHangupTask(MJ.Task.TING, tingTasks);
        }

        var huTasks = this.getSubmitTasks(MJ.Task.HU);
        if (huTasks.length > 0) {
            this._done(MJ.Task.HU, huTasks);
            return;
        }

        var gangTasks = this.getSubmitTasks(MJ.Task.GANG);
        if (gangTasks.length > 0) {
            this._done(MJ.Task.GANG, gangTasks[0]);
            return;
        }

        var pengTasks = this.getSubmitTasks(MJ.Task.PENG);
        if (pengTasks.length > 0) {
            this._done(MJ.Task.PENG, pengTasks[0]);
            return;
        }

        var chiTasks = this.getSubmitTasks(MJ.Task.CHI);
        if (chiTasks.length > 0) {
            this._done(MJ.Task.CHI, chiTasks[0]);
            return;
        }

        var customTasks = this.getSubmitTasks(MJ.Task.CUSTOM);
        if (customTasks.length > 0) {
            this._done(MJ.Task.CUSTOM, customTasks[0]);
            return;
        }

        var passHandler = this.passHandler;
        var passHandlerArgs = this.passHandlerArgs;
        this._done();
        this.room.onHangupTask(MJ.Task.PASS, passHandler, passHandlerArgs);
    },

    _done: function(taskId, arg1, arg2) {
        var source = clone(this.source);
        var count = Object.keys(this.players).length;

        this.reset();

        if (taskId) {
            this.room.onHangupTask(taskId, arg1, arg2);
        }

        if (count > 0) {
            this.room.onHangupTaskDone(source, taskId);
        } else {
            this.room.onHangupTaskNone(source);
        }
    }
}

exports.HangupTask = HangupTask;